module ::Guard
  module RedisHashStoreHelpers
    SPEC_SUPPORT_DIR = Pathname.new(File.expand_path('../test/support', __FILE__))
    REDIS_BIN        = SPEC_SUPPORT_DIR.join('redis-server')
    REDIS_CLI        = SPEC_SUPPORT_DIR.join('redis-cli')
    REDIS_PIDFILE    = SPEC_SUPPORT_DIR.join('redis.pid')
    REDIS_LOGFILE    = SPEC_SUPPORT_DIR.join('redis.log')
    REDIS_PORT       = 6380

    class OnStart
      def call(guard_class, event, *args)
        options = {
          daemonize:  'yes',
          dir:        SPEC_SUPPORT_DIR,
          dbfilename: 'redis.rdb',
          logfile:    REDIS_LOGFILE,
          pidfile:    REDIS_PIDFILE,
          port:       REDIS_PORT
        }
        system "#{REDIS_BIN} #{Guard::RedisHashStoreHelpers.option_hash_to_cli_string options}"

        i = 0
        until File.exist?(REDIS_PIDFILE)
          puts 'Waiting for Redis to start...'
          sleep 1
          i += 1
          raise "Redis didn't start in #{i} seconds." if i >= 5
        end
      end
    end

    class OnStop
      def call(guard_class, event, *args)
        options = {
          p: REDIS_PORT
        }
        system "#{REDIS_CLI} #{Guard::RedisHashStoreHelpers.option_hash_to_cli_string options} shutdown"

        i = 0
        while File.exist?(REDIS_PIDFILE)
          puts 'Waiting for Redis to stop...'
          sleep 1
          i += 1
          raise "Redis didn't stop in #{i} seconds." if i >= 5
        end
      end
    end

    def self.option_hash_to_cli_string(options)
      options.map { |k, v| "-#{'-' if k.length > 1}#{k} #{v}" }.join(' ')
    end
  end
end

guard :minitest do
  callback RedisHashStoreHelpers::OnStart.new, :start_begin
  callback RedisHashStoreHelpers::OnStop.new,  :stop_begin

  watch(%r(^test/(.*)\/?test_(.*)\.rb$))
  watch(%r(^lib/(.*/)?([^/]+)\.rb$))     { |m| "test/#{m[1]}test_#{m[2]}.rb" }
  watch(%r(^test/test_helper\.rb$))      { 'test' }
end
